package com.xddcodec.fs.file.schedule;

import cn.hutool.core.collection.CollUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.xddcodec.fs.file.domain.FileInfo;
import com.xddcodec.fs.file.service.FileInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import java.time.LocalDateTime;
import java.util.List;

import static com.xddcodec.fs.file.domain.table.FileInfoTableDef.FILE_INFO;

/**
 * 回收站清理定时任务
 * 每天凌晨0点05分执行，清理回收站内超过7天的文件
 *
 * @Author: xddcode
 * @Date: 2025/11/15 20:21
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RecycleBinCleanupTask {

    private final FileInfoService fileInfoService;

    /**
     * 定时清理回收站
     * cron表达式：每天00:05执行
     */
    @Scheduled(cron = "0 5 0 * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void cleanupRecycleBin() {
        log.info("========== 开始执行回收站清理任务 ==========");
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        try {
            // 查询需要清理的文件（删除超过7天）
            LocalDateTime expireTime = LocalDateTime.now().minusDays(7);
            List<FileInfo> expiredFiles = findExpiredFiles(expireTime);
            if (CollUtil.isEmpty(expiredFiles)) {
                log.info("回收站无过期文件，任务结束");
                return;
            }
            List<String> fileIds = expiredFiles.stream().map(FileInfo::getId).toList();
            log.info("查询到 {} 个过期文件，开始清理", fileIds.size());
            fileInfoService.permanentlyDeleteFiles(fileIds);
            stopWatch.stop();
            log.info("回收站清理结束, 总计: {} 个, 耗时: {} ms", fileIds.size(), stopWatch.getTotalTimeMillis());
        } catch (Exception e) {
            log.error("回收站清理任务执行异常", e);
            throw e;
        }
    }

    /**
     * 查询过期文件
     */
    private List<FileInfo> findExpiredFiles(LocalDateTime expireTime) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .where(FILE_INFO.IS_DELETED.eq(true))
                .and(FILE_INFO.DELETED_TIME.lt(expireTime))
                .orderBy(FILE_INFO.DELETED_TIME.asc());
        return fileInfoService.list(queryWrapper);
    }
}
